package ocean

import (
    //"fmt"
)

func ParallelOcean(grid [][]int, timesteps, workers int) {
    for i := 0; i < timesteps; i++ {
        ParallelUpdate(grid, i%2, workers)
    }
}

func SerialOcean(grid [][]int, timesteps int) {
    for i := 0; i < timesteps; i++ {
        SerialUpdate(grid, i%2)
    }
}

func SerialUpdate(grid [][]int, red int) {
    rows, cols := len(grid), len(grid[0])

    // Loop through rows
    for i := 1; i < rows-1; i++ {
        for j := 1 + (i+red)%2; j < cols-1; j += 2 {
            //fmt.Print(i,j, " ")
            grid[i][j] = (grid[i][j] + grid[i-1][j] + grid[i+1][j] + grid[i][j-1] + grid[i][j+1])/5
        }
        //fmt.Println()
    }
}

func ParallelUpdate(grid [][]int, red int, workers int) {
    rows := len(grid)
    chunk_size := (rows-2)/workers // Assume work divides evenly
    wait := make(chan int, workers)

    // Loop through rows
    for i := 1; i < rows-chunk_size; i += chunk_size {
        start, stop := i, i+chunk_size
        go ParallelWorker(grid, start, stop, red, wait)
    }
    workers_done := 0
    for workers_done < workers {
        // Wait for each worker to finish
        <-wait
        workers_done++
    }
}


func ParallelWorker(grid [][]int, start, stop, red int, resp chan int) {
    //fmt.Println("PWorker processing rows ", start, stop-1)
    cols := len(grid[0])
    // Loop through rows
    for i := start; i < stop; i++ {
        for j := 1 + (i+red)%2; j < cols-1; j += 2 {
            //fmt.Print(i,j, " ")
            grid[i][j] = (grid[i][j] + grid[i-1][j] + grid[i+1][j] + grid[i][j-1] + grid[i][j+1])/5
        }
        //fmt.Println()
    }
    resp <- 1
}
